実習4: Web2Pyでユーザ登録ページを作ってみよう
実際に手を動かしながら、Web2Py を使ってユーザ登録画面を作ってみましょう。
Web2Pyの起動
まず、Web2Py を起動しましょう
code: bash
$ python web2py.py -i localhost -p 8000 --password パスワード
これで、Web2Py が起動します。
ブラウザで次URLにアクセスします。
http://localhost:8000
ページ下部にある admin のボタンをクリックして管理画面に移動します。
https://gyazo.com/cf11effc9b7ed05a05f6b4dafb12f8fe
新規アプリケーションの作成
画面右側にある「新規アプリケーション」にアプリケーション名 myapp を入力しましょう。
https://gyazo.com/20512f7150e7680c9f394c9130e47137
アプリケーションを編集"myapp" が表示されます。
https://gyazo.com/0ef6cc99d81c7abb84823eaf4624e42f
データベース・スキームの作成
まず、モデルセクションの「作成」をクリックして、モデルファイル db1.py を作成します。
https://gyazo.com/5f996a726fc144293dd9766cb12e32ae
モデルファイル db1.py の左側にある 「編集」ボタンをクリックして、次のコードを追加します。保存するためには、画面上部の"Save File" をクリックするか、Cntrl+S(コントロールキーを押しながらSキー)を押下します。
code: Python
db = DAL('sqlite://storage.sqlite')
db.define_table('registration',
Field('firstname', requires=IS_NOT_EMPTY()),
Field('lastname', requires=IS_NOT_EMPTY()),
Field('username', requires=IS_NOT_EMPTY()),
Field('password', 'password'),
Field('about_you', 'text'),
Field('image', 'upload'))
このコードのはじめの行db = DAL('sqlite://storage.sqlite') でSQLiteのデータベースを作成して、利用を開始しています。
そのあと、db.define_table() でデータベースのテーブルを定義しています。
このdefault.pyが保存されると、Web2Py はこのデータベーススキーマを読み取って、
次のフィールドを持つ registration という名前のテーブルを作成します。
firstname
lastname
gender
username
password
about_you
フォームの作成
次にフォームを作成しましょう。
コントローラ default.py の 「編集」ボタンをクリックして次のコードを最下部に追加します。
code: Python
def form_a():
form = SQLFORM(db.registration)
return dict(form=form)
Web2PyのSQLFORM()関数にデータベースのテーブルオブジェクトを与えているだけですね。
これだけです。
ビューを定義
管理画面のビューの最下部にある「作成」をクリックして、default/form_a.html を作成します。
ここでは、コントローラで定義した関数名と同じビューファイルを用意することがポイントです。
このあと、default/form_a.html の左側にある「編集」をクリックして、
デフォルトで表示さているものを、次のHTMLテンプレートに置き換えてビューに定義します。
code: HTML
<h5> User Registration Form </h5>
<br/>
{{=form}}
<br/>
これで、フォーム画面ができました。
動作確認
ブラウザで次のURLにアクセスしてみましょう。
http://localhost:8000/myapp/default/form_a.html
https://gyazo.com/49abd1228418aae00870c6822bd4da93
必須フィールドの通知
必須フィールドであることをユーザに通知させるためには、コントローラdefault.py で定義した form_a() を次のように修正します。
code: python
def form_a():
form = SQLFORM(db.registration)
if form.process().accepted:
response.flash = 'You have successfully submitted the form’
elif form.errors:
response.flash = 'Please check your form for errors'
else:
response.flash = 'This form cannot be left empty!'
return dict(form=form)
フォームデータの取得
ユーザがこのフォームに入力したデータを、どのように取得すればよいのかを説明します。
まず、コントローラdefault.pyに作成したform_a()関数を思い出してみましょう。
実は前述のform_a() はユーザが入力したデータを追加するだけのものです。
データベースにあるレコードの更新/削除の機能を追加するために、次のようにform_a()を修正しましょう。
code: Python
def form_a():
form = SQLFORM(db.registration,
request.args(0), deletable=True,
upload=URL(r=request, f='download'))
if form.accepts(request.vars, session):
if not form.record:
response.flash = 'Your input data has been submitted.'
else:
if form.vars.delete_this_record:
session.flash = 'User record successfully deleted.'
else:
session.flash = 'User record successfully updated.'
redirect(URL(r=request, f='form_a'))
records = db().select(db.registration.ALL)
return dict(form=form, records=records)
SQLFORM()関数は次のように変わっていて、3つのパラメタ(機能)を追加しました。
code: 修正まえのSQLFORM()
form = SQLFORM(db.registration)
code: 修正後のSQLFORM()
form = SQLFORM(db.registration,
request.args(0), deletable=True,
upload=URL(r=request, f='download'))
request.arg():指定されたフィールドに関連付けられたレコードをフェッチする
deletable=True:フォームレコードを削除/編集できるようにする
upload=URL():画像ファイルへのURLを作成します。
この他は、ユーザの入力データに対して特定の操作が実行されたときに実行されるアクションをコントローラーに通知しています。
次のURLでにアクセスしてエントリを追加しましょう。
http://localhost:8000/myapp/default/form_a
このあと、1番目のエントリを表示させてみましょう。
http://localhost:8000/myapp/default/form_a/1
https://gyazo.com/2b4a28155dd19823a05a758984a5bee1
サブミットされたデータの管理
Web2PyのSQLFORM()関数には、グリッド(grid)という重要な機能があります。
これを利用するには、コントローラ default.py に新しい関数 records() を作成します。
code: Python
def records():
record = SQLFORM.grid(db.registration, user_signature=False)
return locals()
次のURLにアクセスして form_a() を使用して登録されたデータベースの registrationテーブルに送信されたすべてのレコードを確認してみましょう。
http://localhost:8000/myapp/default/records
このページでは、レコードエントリとそれに関連するデータフィールドを表示、編集、更新、削除を行うことができます。 コード開発の時間を大幅に短縮することができ、生産性を大きく高めてくれます。
https://gyazo.com/38a679fc19b5be318dc5e8029ee531b4
ただ、このページにはユーザー認証がないため、データベースのレコードは誰でも操作できてしまいます。ユーザ認証機能を追加するには、user_signature=Trueに設定し、
@auth.requires_login() でデコレートします。
code: Python
@auth.requires_login()
def records():
record = SQLFORM.grid(db.registration, user_signature=True)
return locals()
ここで、次のURLにアクセスしている”Records"の画面をリロードしてみましょう。
http://localhost:8000/myapp/default/records
https://gyazo.com/d2a1608a2732ad093fb49132ed39e924
先程の修正では、@auth.requires_login() でWeb2Py があらかじめ持っている上位レベルのログイン関数を呼び出して、ユーザ認証画面を表示します。これにより、ユーザに"Records"画面を表示する前に、その資格があるかを確認することができます。
また、user_signature = True は、各レコードを保護すること設定します。
つまり、ユーザは"Recrods"画面を見ることができても、個別のフィールドデータを編集したり、削除することができないようになります。
複数のフォームで構成されるページ
複数のフォームから構成されるページを作成してみましょう。
これらのフォームはすべてデータベース内のさまざまなテーブルにリンクされますが、単一のコントローラー関数(今回の例では、form_a())を使用して組み込まれて制御されます。
いま時点では、コントローラdefault.py の form_a() には、すでに1つのフォームがあります。ここに、フォームを追加してみましょう。
データベースの定義
まず、追加するフォーム用にさらに2つ目のテーブルpersonalを定義します。
モデルファイル db1.py を次のように修正します。
code: Python
db.define_table('registration',
Field('firstname', requires=IS_NOT_EMPTY()),
Field('lastname', requires=IS_NOT_EMPTY()),
Field('username', requires=IS_NOT_EMPTY()),
Field('password', 'password'),
Field('image', 'upload'))
db.define_table('personal',
Field('nick_name', requires=IS_NOT_EMPTY()),
Field('address', requires=IS_NOT_EMPTY()),
Field('married', 'boolean'),
Field('zip_code', requires=IS_NOT_EMPTY()))
テーブルpersonalには次のフィールドが定義されます。
Nickname
Address
Married (Check Box)
Zip Code
次に、コントローラー関数form_a()を修正して、2つのフォームを作成するようにします。
code: Python
def form_a():
form1 = SQLFORM(db.registration,
deletable=True, upload=URL(r=request, f='download'))
if form1.accepts(request.vars, session):
redirect(URL(r=request, f='form_a'))
qq = db().select(db.registration.ALL)
form2 = SQLFORM(db.personal,
deletable=True, upload=URL(r=request, f='download'))
if form2.accepts(request.vars, session):
redirect(URL(r=request, f='form_a'))
pp = db().select(db.personal.ALL)
return dict(form1=form1, form2=form2)
ここで、form1とform2の2つのフォームがオブジェクトができました。
これをビュー default/form_a.html で受け取れるようにしましょう。
code: HTML
<h5> User Registration Form </h5>
<br/>
{{=form1}}
{{=form2}}
<br/>
さて、次のURLでにアクセスして動作を確認してみましょう。
http://localhost:8000/myapp/default/form_a
https://gyazo.com/f152a45b594edb0fc8053903a853699e
先程のコントローラ関数form_a()では、フォームを2つ配置するためにはどうするかを強調するために、ユーザに通知するための条件判断をすべて削除しています。
次に、テーブルpersonalについても"Records"画面を表示させるために records() を修正しましょう。
前回追加したユーザ認証画面のためのデコレータはコメントにしておきます。
code: Python
# @auth.requires_login()
def records():
registration = SQLFORM.grid(db.registration, user_signature=False)
personal = SQLFORM.grid(db.personal, user_signature=False)
return locals()
http://localhost:8000/myapp/default/records
https://gyazo.com/aee9052e987f11885ecef029d177c085
複数のデータベーステーブルにリンクされたフォーム
複数のデータベースのテーブルにリンクされたひとつのフォームを定義する場合は、すこし複雑になります。
まず、テーブルprofessinalを作成しましょう。
モデルファイル db1.py に次のコードを追加します。
code: Python
db.define_table('professional',
Field('job_id', requires=IS_NOT_EMPTY()),
Field('job_title', requires=IS_NOT_EMPTY()),
Field('organization', requires=IS_NOT_EMPTY()),
Field('email', requires=IS_NOT_EMPTY()),
Field('supervisor_name', requires=IS_NOT_EMPTY()))
コントローラ関数 form_a() を次のように修正して、1つのフォームがregistrationとprofessinalの2つのテーブルとリンクさせるようにしましょう。
code: Python
def form_a():
form=SQLFORM.factory(db.registration, db.professional,
deletable=True,
upload=URL(r=request, f='download'))
if form.accepts(request.vars, session):
reg = db.registration.insert(
**db.registration._filter_fields(form.vars))
form.vars.client=id
prf = db.professional.insert(
**db.professional._filter_fields(form.vars))
redirect(URL(r=request, f='form_a'))
return dict(form=form)
ここでは、db.registration.insert() と db.professional.insert() メソッドは両方のデータベーステーブルにそれぞれ関連付けられたデータを追加します。
フォームが変更されているのでビューdefault/form_a.htmlも修正します。
code: HTML
<h5> User Registration Form </h5>
<br/>
{{=form}}
<br/>
次のURLでにアクセスしてフォームの表示を確認してみましょう。
http://localhost:8000/myapp/default/form_a
https://gyazo.com/5e3cd2bbaa0fa602ed43ca027b83571c
form_a()で追加されたレコードを表示するために、records()関数を修正しましょう。
code: Python
# @auth.requires_login()
def records():
registration = SQLFORM.grid(db.registration, user_signature=False)
personal = SQLFORM.grid(db.personal, user_signature=False)
proffesinal = SQLFORM.grid(db.professional, user_signature=False)
return locals()
次のURLにアクセスして”Records"画面を確認してみましょう。
http://localhost:8000/myapp/default/records
https://gyazo.com/9cad8329210e934499ac84ea0c011c24
Web2Py を使った感想はどうです?
圧倒的な開発効率を実感できたのではないでしょうか。